﻿'Copyright 2010 Brian L. Crawford

'Licensed under the Apache License, Version 2.0 (the "License");
'you may not use this file except in compliance with the License.
'You may obtain a copy of the License at

'    http://www.apache.org/licenses/LICENSE-2.0

'Unless required by applicable law or agreed to in writing, software
'distributed under the License is distributed on an "AS IS" BASIS,
'WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
'See the License for the specific language governing permissions and
'limitations under the License.

'This software uses Microsoft .Net framework used with permission from      
'Microsoft. Microsoft, .Net Framework, Visual Studio, Visual Basic, Visual C++ 
'remain the trademark and copyright of Microsoft and are subject to their 
'individual licenses.


Imports System.Windows.Forms
Imports System.Threading
Imports System.Timers
Imports System.ComponentModel

Public Class Form1
    Inherits Form
    Dim Start_Folder As New Filecollection
    Dim Sec_Folder As New Filecollection
    Dim checkboxstatus, folder1status, folder2status As Boolean
    Dim Savepath As String
    ReadOnly Property Path()
        Get
            Return Savepath
        End Get
    End Property
    Public Sub New()
        InitializeComponent()
        ' Create ToolStripPanel controls.
        Dim tspTop As New ToolStripPanel()

        ' Dock the ToolStripPanel controls to the edges of the form.
        tspTop.Dock = DockStyle.Top
        ' Create ToolStrip controls to move among the 
        ' ToolStripPanel controls.
        ' Create the "Top" ToolStrip control and add
        ' to the corresponding ToolStripPanel.
        Dim tsTop As New ToolStrip()
        tsTop.Items.Add("Top")
        tspTop.Join(tsTop)

        ' Create a MenuStrip control with a new window.
        Dim ms As New MenuStrip()
        Dim windowMenu As New ToolStripMenuItem("Window")
        Dim windowNewMenu As New ToolStripMenuItem("New", Nothing, New EventHandler(AddressOf windowNewMenu_Click))
        windowMenu.DropDownItems.Add(windowNewMenu)
        CType(windowMenu.DropDown, ToolStripDropDownMenu).ShowImageMargin = False
        CType(windowMenu.DropDown, ToolStripDropDownMenu).ShowCheckMargin = True

        ' Assign the ToolStripMenuItem that displays 
        ' the list of child forms.
        ms.MdiWindowListItem = windowMenu

        ' Add the window ToolStripMenuItem to the MenuStrip.
        ms.Items.Add(windowMenu)

        ' Dock the MenuStrip to the top of the form.
        ms.Dock = DockStyle.Top

        ' The Form.MainMenuStrip property determines the merge target.
        Me.MainMenuStrip = ms

        ' Add the ToolStripPanels to the form in reverse order.
        Me.Controls.Add(tspTop)

        ' Add the MenuStrip last.
        ' This is important for correct placement in the z-order.
        Me.Controls.Add(ms)
    End Sub

    ' This event handler is invoked when 
    ' the "New" ToolStripMenuItem is clicked.
    ' It creates a new Form and sets its MdiParent 
    ' property to the main form.
    Private Sub windowNewMenu_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim f As New Form()
        f.MdiParent = Me
        f.Text = "Form - " + Me.MdiChildren.Length.ToString()
        f.Show()
    End Sub

    Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Start_Folder.do_Path = GetBrowse("Select the Reference folder; usually the EDDS/OTP folder", Sec_Folder.do_Path)
        Savepath = Start_Folder.do_Path
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        labelposition(Label1, 12, 0)
        'labelposition(Label2, 12, 243)
        Start_Folder.do_Path = Nothing
        Sec_Folder.do_Path = Nothing
        Button3.Enabled = True
    End Sub

    Public Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Sec_Folder.do_Path = GetBrowse("Select the Folder containing files to compare against the EDDS folder", Start_Folder.do_Path)
    End Sub

    Public Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        'first check if the PATH is set for each of the folder classes
        If Start_Folder.do_Path = Nothing Then
            'add something to do when path is null
            Exit Sub
        ElseIf Sec_Folder.do_Path = Nothing Then
            'add something to do when path is null
            Exit Sub
        End If
        'Need to make sure that the listboxes are clear and that all of the objects are ready for the search
        Form2.Show() 'show form2 
        Form2.Left = Me.Left + Me.Width + 1 'tell where to open form2
        Form2.Top = Me.Top 'tell where to open form2
        If checkboxstatus = True Then
            BackgroundWorker1.RunWorkerAsync(Start_Folder.do_Path) 'uncomment for multi-threading
            BackgroundWorker2.RunWorkerAsync(Sec_Folder.do_Path)   'uncomment for multi-threading  
            BackgroundWorker3.RunWorkerAsync()                     'uncomment for multi-threading
        Else
            'do_comparefiles()  'old single threaded
            BackgroundWorker1.RunWorkerAsync() 'uncomment for multi-threading
            BackgroundWorker2.RunWorkerAsync()   'uncomment for multi-threading  
            BackgroundWorker3.RunWorkerAsync()                     'uncomment for multi-threading
        End If
        Button3.Enabled = False
        Form2.Button3.Enabled = True
    End Sub

    Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
        checkboxstatus = sender.checked()
    End Sub



    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        ' Get the BackgroundWorker object that raised this event.
        Dim worker As BackgroundWorker = _
            CType(sender, BackgroundWorker)

        ' Assign the result of the computation
        ' to the Result property of the DoWorkEventArgs
        ' object. This is will be available to the 
        ' RunWorkerCompleted eventhandler.

        Dim arg As String = e.Argument
        If arg = Nothing Then
            'For the case when the subfiles isn't checked.  probably should use the value of the check box
            'rather than testing to see if i'm passing folders to the backgroundworker.
            Start_Folder.collect_files(Start_Folder.do_Path())
        Else
            Start_Folder.collect_files(Start_Folder.do_Path())
            e.Result = Start_Folder.collect_subfiles(arg, worker, e)
        End If
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        'add results of the search to the listbox
        Form2.ListBox1.Items.Add(e.UserState)
        Form2.ListBox1.SetSelected(Form2.ListBox1.Items.Count - 1, True)
        Form2.ListBox1.SetSelected(Form2.ListBox1.Items.Count - 1, False)
    End Sub

    ' This event handler deals with the results of the
    ' background operation.
    Private Sub backgroundWorker1_RunWorkerCompleted( _
    ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    Handles BackgroundWorker1.RunWorkerCompleted

        ' First, handle the case where an exception was thrown.
        If (e.Error IsNot Nothing) Then
            MessageBox.Show(e.Error.Message)
        ElseIf e.Cancelled Then
            ' Next, handle the case where the user canceled the 
            ' operation.
            ' Note that due to a race condition in 
            ' the DoWork event handler, the Cancelled
            ' flag may not have been set, even though
            ' CancelAsync was called.
            Form2.ListBox1.Items.Clear()
        Else
            ' Finally, handle the case where the operation succeeded.
            folder1status = e.Result
        End If

        ' Enable the UpDown control.
        'Me.numericUpDown1.Enabled = True

        ' Enable the Start button.
        'startAsyncButton.Enabled = True

        ' Disable the Cancel button.
        'cancelAsyncButton.Enabled = False
    End Sub 'backgroundWorker1_RunWorkerCompleted

    Private Sub BackgroundWorker2_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker2.DoWork
        ' Get the BackgroundWorker object that raised this event.
        Dim worker As BackgroundWorker = _
            CType(sender, BackgroundWorker)

        ' Assign the result of the computation
        ' to the Result property of the DoWorkEventArgs
        ' object. This is will be available to the 
        ' RunWorkerCompleted eventhandler.

        Dim arg As String = e.Argument
        If arg = Nothing Then
            'For the case when the subfiles isn't checked.  probably should use the value of the check box
            'rather than testing to see if i'm passing folders to the backgroundworker.
            Sec_Folder.collect_files(Sec_Folder.do_Path())
        Else
            Sec_Folder.collect_files(Sec_Folder.do_Path())
            e.Result = Sec_Folder.collect_subfiles(arg, worker, e)
        End If
    End Sub

    Private Sub BackgroundWorker2_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker2.ProgressChanged
        'add results of the search to the listbox
        Form2.ListBox2.Items.Add(e.UserState)
        Form2.ListBox2.SetSelected(Form2.ListBox2.Items.Count - 1, True)
        Form2.ListBox2.SetSelected(Form2.ListBox2.Items.Count - 1, False)
    End Sub

    ' This event handler deals with the results of the
    ' background operation.
    Private Sub backgroundWorker2_RunWorkerCompleted( _
    ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    Handles BackgroundWorker2.RunWorkerCompleted

        ' First, handle the case where an exception was thrown.
        If (e.Error IsNot Nothing) Then
            MessageBox.Show(e.Error.Message)
        ElseIf e.Cancelled Then
            ' Next, handle the case where the user canceled the 
            ' operation.
            ' Note that due to a race condition in 
            ' the DoWork event handler, the Cancelled
            ' flag may not have been set, even though
            ' CancelAsync was called.
            Form2.ListBox2.Items.Clear()
        Else
            ' Finally, handle the case where the operation succeeded.
            folder2status = e.Result
        End If

        ' Enable the UpDown control.
        'Me.numericUpDown1.Enabled = True

        ' Enable the Start button.
        'startAsyncButton.Enabled = True

        ' Disable the Cancel button.
        'cancelAsyncButton.Enabled = False
    End Sub 'backgroundWorker2_RunWorkerCompleted
    Private Sub BackgroundWorker3_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker3.DoWork
        ' Get the BackgroundWorker object that raised this event.
        Dim worker As BackgroundWorker = _
            CType(sender, BackgroundWorker)

        ' Assign the result of the computation
        ' to the Result property of the DoWorkEventArgs
        ' object. This is will be available to the 
        ' RunWorkerCompleted eventhandler.
        waitonthreads(worker, e)
    End Sub

    ' This event handler deals with the results of the
    ' background operation.
    Private Sub backgroundWorker3_RunWorkerCompleted( _
    ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    Handles BackgroundWorker3.RunWorkerCompleted

        ' First, handle the case where an exception was thrown.
        If (e.Error IsNot Nothing) Then
            MessageBox.Show(e.Error.Message)
            Button3.Enabled = True
        ElseIf e.Cancelled Then
            ' Next, handle the case where the user canceled the 
            ' operation.
            ' Note that due to a race condition in 
            ' the DoWork event handler, the Cancelled
            ' flag may not have been set, even though
            ' CancelAsync was called.
            resetfolderstatus()
            Button3.Enabled = True
        Else
            ' Finally, handle the case where the operation succeeded.
            'do_comparefiles()
            'Now to compare files in the two boxes and update the display to show what we find.
            'Will need to clear the contents of the lists before we try to start a new search.
            'enable the button on form2 to compare the files.
            Form2.Button3.Enabled = True
            Form2.Button2.Enabled = True
            Button3.Enabled = True
        End If
        'add controls for buttons
        ' Enable the UpDown control.
        'Me.numericUpDown1.Enabled = True

        ' Enable the Start button.
        'startAsyncButton.Enabled = True

        ' Disable the Cancel button.
        'cancelAsyncButton.Enabled = False
    End Sub 'backgroundWorker3_RunWorkerCompleted


    'this block needs to become a timer or method which will check periodically if the two 
    'threads have finished before running the comparison
    Dim myTimer As New System.Windows.Forms.Timer()
    Dim alarmCounter As Integer = 1
    Dim exitFlag As Boolean = False

    ' This is the method to run when the timer is raised.
    Sub TimerEventProcessor(ByVal myObject As Object, _
                                           ByVal myEventArgs As EventArgs)
        myTimer.Stop()

        ' check if background threads finished
        If folder1status = True Then
            If folder2status = True Then
                exitFlag = True
            End If
        Else
            ' Stops the timer.
            'exitFlag = True
            ' Restarts the timer and increments the counter.
            alarmCounter += 1
            myTimer.Enabled = True
        End If
    End Sub

    Public Function waitonthreads(ByVal worker As BackgroundWorker, ByVal e As DoWorkEventArgs)
        Try
            'check for cancellation
            If worker.CancellationPending = True Then Exit Function
            ' Adds the event and the event handler for the method that will
            ' process the timer event to the timer.
            AddHandler myTimer.Tick, AddressOf TimerEventProcessor
            ' Sets the timer interval to 1 seconds.
            myTimer.Interval = 1000
            myTimer.Start()
            ' Runs the timer, and raises the event.
            While exitFlag = False
                'check for cancellation
                If worker.CancellationPending = True Then Exit Function
                ' Processes all the events in the queue.
                Application.DoEvents()
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString)
        End Try
    End Function

    Sub do_comparefiles()
        CompareFiles(Start_Folder, Sec_Folder, "Select a Folder to save the Comparison report in...")
    End Sub
    Sub resetfolderstatus()
        Start_Folder.clear()            'clear items in my folder collections
        Sec_Folder.clear()
        folder1status = False
        folder2status = False
        exitFlag = False
        Form2.ListBox1.Items.Clear()
        Form2.ListBox2.Items.Clear()
        Form2.ListBox1.Refresh()
        Form2.ListBox2.Refresh()
        Button3.Enabled = True          'this line can't be here if i call this procedure when button 3 is clicked
        Form2.Button2.Enabled = False
        Form2.Button3.Enabled = False
    End Sub
    Sub labelposition(ByVal myLabel As Label, ByVal x As Integer, ByVal y As Integer)
        'myLabel.AutoSize = True
        myLabel.Location = New Point(x, y)
        myLabel.Width = Me.Width - 12
    End Sub

    Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        labelposition(Label1, 12, 0)
        'labelposition(Label2, 12, 243)
    End Sub
End Class
'todo : go thru and dispose() of veriables, procedures, and classes that are no longer needed.